/*
 * @Author: Mr.Mao
 * @Date: 2021-05-19 21:33:54
 * @LastEditTime: 2021-06-24 01:20:32
 * @Description: 
 * @LastEditors: Mr.Mao
 * @autograph: 任何一个傻子都能写出让电脑能懂的代码，而只有好的程序员可以写出让人能看懂的代码
 */
import { Document } from 'mongoose'
import { Prop, ExtractPropTypes } from 'vue';

/** 取出必选 key */
type RequiredKeys<T> = {
  [K in keyof T]: T[K] extends { required: true; } | { default: any; } | any[] ? T[K] extends { default: undefined | (() => undefined); } ? never : K : never;
}[keyof T]

/** 取出可选 key */
type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>;

/** 转换 Constructor 类型 */
type InferPropType<T> =
  [T] extends [null] ? any :
  [T] extends [{ type: null | true; }] ? any :
  [T] extends [ObjectConstructor | { type: ObjectConstructor; }] ? Record<string, any> :
  [T] extends [BooleanConstructor | { type: BooleanConstructor; }] ? boolean :
  [T] extends [DateConstructor | { type: DateConstructor; }] ? Date :
  [T] extends [Prop<infer V, infer D>] ? (unknown extends V ? D : V) :
  [T] extends [{ [key: string]: any }] ? { [K in keyof T]: InferPropType<T[K]> } : T;

/** 假如遇到数组, 则通过占位符解构类型转换, 不然则直接转换 */
type TakeTypeConstructor<T> = T extends { type: infer I }[] ? InferPropType<I>[] : InferPropType<T>

/** 转换校验类型, 将必选与可选合并 */
export type DocumentTransform<O> = O extends object ?
  { [K in RequiredKeys<O>]: TakeTypeConstructor<O[K]> } & { [K in OptionalKeys<O>]?: InferPropType<O[K]> } :
  { [K in string]: any; }

interface BaseDocument extends Document {
  _id: string
  __v: number
}
export interface TUserInfo extends BaseDocument {
  avatar: string
  gender: string
  account: string
  lastLoginTime: number
  password?: string
}